.TITLE DCQUE - DC Queue Maintenance .IDENT /05.00/ .IFDF D$$CHE .PSECT DC$QUE,RO,I ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; (authorship and previous history lost to posterity) ; Modified By: ; ; J. Kauffman 17-Feb-87 1.01 ; JRK330 - Convert E.UCBX to E.UCB for deferred write support ; ; Re-mastered for RSX-11M-PLUS V4.4 by: ; ; L. B. McCulley 26-Jan-92 4.00 ; LBM409 -- track changes to other modules ; ; D. Carroll 11-August-1992 4.00b ; DC140 -- Insure ES.WPL CEDs are not included into ; the region age list. ; ; D. Carroll 10-October-1992 4.01 ; DC143 -- Include bugcheck codes for errors ; ; D. Carroll 10-Dec-1992 4.02 ; DC157 -- Include hash table support ; ; Modified for RSX-11M-PLUS V4.6 by: ; ; D. Carroll 8-Jan-1996 05.00 ; DC430 - Include support for 32-bit LBNs ; ; .SBTTL QINLBN - Insert CED into LBN queue ; ; This routine will use the temporary cell, H.TMP ; to place the specified CED into the ascending LBN ; queue for a device. The two temporaries are supplied by ; SEARCH (DCSUB), and are retained in order to position within ; the LBN list only once, thereby increasing cache performance. ; ; Passed: ; R0 -> CED to be inserted into the LBN queue. ; ; Returned: ; All registers preserved ; ; Processing: ; ; CASE TMP1 TMP2 ; ----------------------------- ---- ---- ; I. No elements in queue EQ 0 EQ 0 ; II. Becomes first in queue EQ 0 NE 0 ; III. Becomes last in queue NE 0 EQ 0 ; IV. Inserted within queue NE 0 NE 0 ; ----------------------------- ---- ---- ; ; The following is performed: ; ; IF TMP1=0 ; IF TMP2=0 ; { ;Case I. ; CURR.PREV <- 0 ; CURR.NEXT <- 0 ; X.CCED <- CURR ; X.CCED+2 <- CURR ; } ; ELSE 0> ; { ;Case II. ; CURR.PREV <- 0 ; CURR.NEXT <- TMP2 ; TMP2.PREV <- CURR ; X.CCED <- CURR ; } ; ELSE 0> ; IF TMP2=0 ; { ;Case III. ; CURR.PREV <- TMP1 ; CURR.NEXT <- 0 ; TMP1.NEXT <- CURR ; X.CCED+2 <- CURR ; } ; ELSE 0> ; { ;Case IV. ; CURR.PREV <- TMP1 ; TMP1.NEXT <- CURR ; CURR.NEXT <- TMP2 ; TMP2.PREV <- CURR ; } ; END ; END ; QINLBN:: CLR E.LPRV(R0) ;CURR.PREV <- 0 CLR E.LNXT(R0) ;CURR.NEXT <- 0 MOV R1,-(SP) ;Obtain a work register BITB #CS.DBG,APRD.BASE+H.CSTS ; debug enabled? BEQ 999$ ; if EQ, nope ... CLR -(SP) ; reserve a stack word MOV KISAR6,-(SP) ; save mapping MOV U.UCBX(R5),KISAR6 ; map ucbx MOV APR6.BASE+X.CCED,2(SP) ; get first ced MOV (SP)+,KISAR6 ; restore mapping MOV (SP)+,R1 ; get ced pointer BEQ 999$ ; done already 991$: CMP R0,R1 ; already in list? BNE 992$ ; no, go on FATAL$ BE.QIN ; element already in queue 992$: MOV E.LNXT(R1),R1 ; get next ced BNE 991$ ; continue scan 999$: MOV APRD.BASE+H.TMP,R1 ;Insert at beginning of queue? BNE 20$ ;No if NE ; ; here we insert this CED at beginning of list ; MOV KISAR6,-(SP) ;Save partition mapping MOV U.UCBX(R5),KISAR6 ;Map the UCB extension MOV APR6.BASE+X.CCED,R1 ;R1-> next (was first) CED BNE 5$ ; got it, don't set ptr to list end MOV R0,APR6.BASE+X.CCED+2 ;X.CCED+2 <- CURR 5$: MOV R0,APR6.BASE+X.CCED ;X.CCED <- CURR 7$: MOV (SP)+,KISAR6 ;Restore partition mapping 10$: MOV R1,E.LNXT(R0) ;set link to next CED BEQ 40$ ;no next CED, done MOV R0,E.LPRV(R1) ;set backpointer in next CED BR 40$ ;done, exit ; ; here we insert following CED pointed to by H.TMP (now in R1) ; 20$: MOV R1,E.LPRV(R0) ;set backpointer to prev MOV E.LNXT(R1),E.LNXT(R0) ;point to next CED MOV R0,E.LNXT(R1) ;point prev to new next MOV E.LNXT(R0),R1 ;point to next CED BEQ 30$ ; there is none, set list end MOV R0,E.LPRV(R1) ;set backpointer in next CED BR 40$ 30$: MOV KISAR6,-(SP) ;Save partition mapping MOV U.UCBX(R5),KISAR6 ;Map the UCB extension MOV R0,APR6.BASE+X.CCED+2 ;X.CCED+2 <- CURR MOV (SP)+,KISAR6 ;Remap the partition 40$: BITB #CS.DBG,APRD.BASE+H.CSTS ; debug enabled? BEQ 901$ ; nope ignore it MOV E.LPRV(R0),R1 ; check prev < current BEQ 882$ ; no prev, must be ok CMP E.LBNL+2(R0),E.LBNL+2(R1) ; check order ;DC430 BHI 881$ ; ok, not out of order ;**-1 BLO 899$ ; report disorderly conduct CMP E.LBNL(R0),E.LBNL(R1) ; finish check BLO 899$ ; report disorder 881$: CMP E.LBNH+2(R1),E.LBNL+2(R0) ; overlap? ;DC430 BHI 899$ ; yep ;**-1 BLO 882$ ; if lo, allright CMP E.LBNH(R1),E.LBNL(R0) ; BHI 899$ 882$: MOV E.LNXT(R0),R1 ; now check next > current BEQ 901$ ; no next, must be ok CMP E.LBNL+2(R0),E.LBNL+2(R1) ; check order ;DC430 BLO 891$ ; ok, not out of order ;**-1 BHI 899$ ; report disorderly conduct CMP E.LBNL(R0),E.LBNL(R1) ; finish check BHI 899$ 891$: CMP E.LBNH+2(R0),E.LBNL+2(R1) ; overlap here? ;DC430 BHI 899$ ; yes, flag it ;**-1 BLO 901$ CMP E.LBNH(R0),E.LBNL(R1) BLOS 901$ 899$: FATAL$ BE.LBN ; report error 901$: MOV (SP)+,R1 ;Restore saved R1 RETURN .SBTTL QRMLBN - Remove CED from LBN queue ; ; Passed: ; R0 -> CED to remove ; ; Returned: ; All registers preserved ; ; Processing: ; ; CASE .PREV .NEXT ; ----------------------------- ----- ----- ; I. Only element in queue EQ 0 EQ 0 ; II. First element in queue EQ 0 NE 0 ; III. Last element in queue NE 0 EQ 0 ; IV. Element within queue NE 0 NE 0 ; ----------------------------- ----- ----- ; ; IF CURR.PREV=0 ; IF CURR.NEXT=0 ; { ; X.CCED <- 0 ; X.CCED+2 <- 0 ; } ; ELSE 0> ; { ; X.CCED <- CURR.NEXT ; NEXT.PREV <- 0 ; } ; END ; ELSE 0> ; IF CURR.NEXT=0 ; { ; X.CCED+2 <- CURR.PREV ; PREV.NEXT <- 0 ; } ; ELSE 0> ; { ; PREV.NEXT <- CURR.NEXT ; NEXT.PREV <- CURR.PREV ; } ; END ; END ; QRMLBN:: MOV R1,-(SP) ;Get a work register MOV E.LPRV(R0),R1 ;Is this the first extent? BNE 20$ ;No if NE MOV E.LNXT(R0),R1 ;Is this the last one? BNE 10$ ;No if NE MOV KISAR6,-(SP) ;Save the partition mapping MOV E.UCB(R0),R1 ;Get pointer to UCB address MOV U.UCBX(R1),KISAR6 ;Map the UCBX CLR APR6.BASE+X.CCED ;X.CCED <- 0 CLR APR6.BASE+X.CCED+2 ;X.CCED+2 <- 0 MOV (SP)+,KISAR6 ;Remap te partition BR 40$ ;And exit 10$: MOV E.LNXT(R0),R1 ;Get NEXT MOV KISAR6,-(SP) ;Save the partition mapping MOV R0,-(SP) ;Save the CED address across mapping MOV E.UCB(R0),R0 ;Get the UCB address from CED MOV U.UCBX(R0),KISAR6 ;Map the UCBX MOV (SP)+,R0 ;Restore the CED address MOV R1,APR6.BASE+X.CCED ;X.CCED <- CURR.NEXT 15$: MOV (SP)+,KISAR6 ;Remap te partition CLR E.LPRV(R1) ;NEXT.PREV <- 0 BR 40$ ;And exit 20$: MOV E.LNXT(R0),R1 ;Last in queue? BNE 30$ ;No if NE MOV E.LPRV(R0),R1 ; MOV KISAR6,-(SP) ;Save the partition mapping MOV R0,-(SP) ;Save the CED address across mapping MOV E.UCB(R0),R0 ;Get the UCB address from CED MOV U.UCBX(R0),KISAR6 ;Map the UCBX MOV (SP)+,R0 ;Restore the CED address MOV R1,APR6.BASE+X.CCED+2 ;X.CCED+2 <- CURR.PREV MOV (SP)+,KISAR6 ;Remap te partition CLR E.LNXT(R1) ;PREV.NEXT <- 0 BR 40$ ;And exit 30$: MOV E.LPRV(R0),R1 ;Get PREV MOV E.LNXT(R0),E.LNXT(R1) ;PREV.NEXT <- CURR.NEXT MOV E.LNXT(R0),R1 ;Get NEXT MOV E.LPRV(R0),E.LPRV(R1) ;NEXT.PREV <- CURR.PREV 40$: MOV (SP)+,R1 ;Restore saved R1 INC E.LNXT(R0) ; invalidate obsolete links so... INC E.LPRV(R0) ; XDT will report attempted usage RETURN ;And all done .SBTTL QUPAGE - Move CED to end of age queue ; ; Passed: ; R0 -> CED to update ; ; Returned: ; All registers preserved ; QUPAGE:: BITB #ES.WPL,E.STAT(R0) ; is this a write place holder? BNE 10$ ; if NE, yes, no age list association CALL QRMAGE ; Remove it from list CALL QADAGE ; Add it at end of list 10$: RETURN .SBTTL QRMAGE - Remove CED from age queue ; ; Passed: ; R0 -> CED to remove from age list ; ; Returned: ; All registers preserved ; ; Processing: ; ; CASE .PREV .NEXT ; ------------------------------ ----- ----- ; I. Element is only in queue EQ 0 EQ 0 ; II. Element is first in queue EQ 0 NE 0 ; III. Element is last in queue NE 0 EQ 0 ; IV. Element is within queue NE 0 NE 0 ; ------------------------------ ----- ----- ; ; IF CURR.PREV=0 ; IF CURR.NEXT=0 ; { ; H.CEDH <- 0 ; H.CEDH+2 <- 0 ; } ; ELSE 0> ; { ; H.CEDH <- CURR.NEXT ; NEXT.PREV <- 0 ; } ; ELSE 0> ; IF CURR.NEXT=0 ; { ; PREV.NEXT <- 0 ; H.CEDH+2 <- CURR.PREV ; } ; ELSE 0> ; { ; NEXT.PREV <- CURR.PREV ; PREV.NEXT <- CURR.NEXT ; } ; END ; END ; QRMAGE:: BITB #ES.WPL,E.STAT(R0) ; is this a write place holder? BNE 50$ ; if NE, yes, skip this ... MOV R1,-(SP) ;Get a work register MOV E.APRV(R0),R1 ;First in queue? BNE 20$ ;No if NE MOV E.ANXT(R0),R1 ;Only in queue? BNE 10$ ;No if NE CLR APRD.BASE+H.CEDH ;Initialize the pointers CLR APRD.BASE+H.CEDH+2 BR 40$ 10$: MOV R1,APRD.BASE+H.CEDH ;H.CEDH <- NEXT CLR E.APRV(R1) ;NEXT.PREV <- 0 BR 40$ 20$: MOV E.ANXT(R0),R1 ;Last in queue? BNE 30$ ;No if NE MOV E.APRV(R0),R1 ;Get PREV CLR E.ANXT(R1) ;PREV.NEXT <- 0 MOV R1,APRD.BASE+H.CEDH+2 ;H.CEDH+2 <- 0 BR 40$ 30$: MOV E.APRV(R0),E.APRV(R1) ;NEXT.PREV <- CURR.PREV MOV E.APRV(R0),R1 ;Get PREV MOV E.ANXT(R0),E.ANXT(R1) ;PREV.NEXT <- CURR.NEXT 40$: MOV (SP)+,R1 ;Restore saved R1 50$: RETURN .SBTTL QADAGE - Add a CED at the end of the age queue ; ; Passed: ; R0 -> CED to append to list ; ; Returned: ; All registers preserved ; ; Processing: ; ; CASE H.CEDH H.CEDH+2 ; ----------------------------- ------ -------- ; I. No elements in queue EQ 0 EQ 0 ; II. First element in queue EQ 0 NE 0 ; III. Last element in queue NE 0 EQ 0 ; IV. Element within queue NE 0 NE 0 ; ----------------------------- ------ -------- ; ; CURR.NEXT <- 0 ; IF H.CEDH+2=0 ; { ; H.CEDH <- CURR ; H.CEDH+2 <- CURR ; CURR.PREV <- 0 ; } ; ELSE 0> ; { ; CURR.PREV <- H.CEDH+2 ; PREV.NEXT <- CURR ; H.CEDH+2 <- CURR ; } ; END ; QADAGE:: BITB #ES.WPL,E.STAT(R0) ; is this a write place holder? BNE 30$ ; if NE, yes, don't insert into list MOV R1,-(SP) ;Get a work register CLR E.ANXT(R0) ;CURR.NEXT <- 0 MOV APRD.BASE+H.CEDH+2,R1 ;Is list null? BNE 10$ ;No if NE MOV R0,APRD.BASE+H.CEDH ;This extent becomes first and last MOV R0,APRD.BASE+H.CEDH+2 ;in queue CLR E.APRV(R0) ;Indicate no previous either BR 20$ ;And exit 10$: MOV R1,E.APRV(R0) ;CURR.PREV <- H.CEDH+2 MOV R0,E.ANXT(R1) ;PREV.NEXT <- CURR MOV R0,APRD.BASE+H.CEDH+2 ;H.CEDH+2 <- CURR 20$: MOV (SP)+,R1 ;Restore saved R1 30$: RETURN .SBTTL QRMBUF - Remove a CED from memory buffer list ; ; QRMBUF - Remove a CED from memory buffer list ; ; NOTE: E.BNXT is assumed to be offset 0 within CED .iif ne,e.bnxt .error E.BNXT ; E.BNXT assumed zero and isn't QRMBUF:: MOV R1, -(SP) ; save work register MOV E.BPRV(R0), R1 ;Point to previous CED MOV (R0), (R1) ;Point previous next to our next MOV (R0), R1 ;R1 -> next CED now MOV E.BPRV(R0),E.BPRV(R1) ;Point next back to our previous ;+ ; This section will attempt to set a logical starting point ; for any subsequent searches, such that GETFRE will not have ; to chain through [n] CEDs until encountering free space. ;- MOV APRD.BASE+H.CMDF,R1 ; get the base address CED BEQ 10$ ; if EQ, nothing there, use this CMP E.PHYA(R0),E.PHYA(R1) ; is this CED a lower base address? BHI 20$ ; if HI, nope, leave previous entry 10$: MOV E.BPRV(R0),APRD.BASE+H.CMDF ; set starting CED entry for GETBUF 20$: INC (R0) ; make links odd INC E.BPRV(R0) MOV (SP)+, R1 ; restore work register RETURN .ENDC ; .IFDF D$$CHE .END